#pragma once
#include "../common/net.hpp"
#include "../common/message.hpp"
#include <jsoncpp/json/json.h>
#include <vector>
#include <unordered_map>

namespace RPC
{
    namespace Server
    {
        enum class VType
        {
            INTEGRAL = 0,
            NUMERIC,
            STRING,
            BOOL,
            ARRAY,
            OBJECT
        };
        class ServiceDiscribe
        {
        public:
            using Ptr = std::shared_ptr<ServiceDiscribe>;
            using ServiceCallBack = std::function<bool(const Json::Value &, Json::Value &)>;
            using ParamsDescribe = std::pair<std::string, VType>;

            ServiceDiscribe(std::string &&name, ServiceCallBack &&callback,
                            std::vector<ParamsDescribe> &&params_describe, const VType &return_type)
                : _method_name(name), _callback(callback),
                  _params_describe(params_describe), _return_type(return_type)
            {
            }

            std::string method() const
            {
                return _method_name;
            }

            bool paramCheck(const Json::Value &params) const
            {
                // 对params进行参数校验，判断所描述的参数字段是否存在，类型是否一致
                for (const auto &x : _params_describe)
                {
                    if (params.isMember(x.first) == false)
                    {
                        ERROR_LOG("请求参数校验失败！");
                        return false;
                    }
                    if (checkType(x.second, params[x.first]) == false)
                    {
                        ERROR_LOG("参数类型校验失败!");
                        return false;
                    }
                }
                return true;
            }

            bool call(const Json::Value &req, Json::Value &res)
            {
                bool ret = _callback(req, res);
                if (ret == false)
                {
                    ERROR_LOG("返回值类型错误！");
                    return false;
                }
                return true;
            }

        private:
            bool checkReturn(Json::Value res)
            {
                return checkType(_return_type, res);
            }
            bool checkType(VType type, const Json::Value &val) const
            {
                switch (type)
                {
                case VType::BOOL:
                    return val.isBool();
                case VType::ARRAY:
                    return val.isArray();
                case VType::INTEGRAL:
                    return val.isIntegral();
                case VType::NUMERIC:
                    return val.isNumeric();
                case VType::OBJECT:
                    return val.isObject();
                case VType::STRING:
                    return val.isString();
                }
                ERROR_LOG("请求类型校验失败！");
                return false;
            }

        private:
            std::string _method_name;                     // 方法名字
            ServiceCallBack _callback;                    // 回调处理
            std::vector<ParamsDescribe> _params_describe; // 参数描述
            VType _return_type;                           // 返回值类型校验
        };
        // 建筑者模式，使得服务描述在建筑好，就不能在修改了，这样在就不用考虑并发的问题
        class SDFactory
        {
        public:
            using Ptr = std::shared_ptr<SDFactory>;
            void setMethod(const std::string &method) { _method_name = method; }
            void setCallback(const ServiceDiscribe::ServiceCallBack &call) { _callback = call; }
            void setParamsDescribe(const std::vector<ServiceDiscribe::ParamsDescribe> &params)
            {
                _params_describe = params;
            }
            void setReturnType(const VType &returnvalue)
            {
                _return_type = returnvalue;
            }

            ServiceDiscribe::Ptr build()
            {
                return std::make_shared<ServiceDiscribe>(std::move(_method_name), std::move(_callback),
                                                         std::move(_params_describe), _return_type);
            }

        private:
            std::string _method_name;                                      // 方法名字
            ServiceDiscribe::ServiceCallBack _callback;                    // 回调处理
            std::vector<ServiceDiscribe::ParamsDescribe> _params_describe; // 参数描述
            VType _return_type;                                            // 返回值类型校验
        };

        class ServiceManager
        {
        public:
            using Ptr = std::shared_ptr<ServiceManager>;
            void create(const ServiceDiscribe::Ptr &service)
            {
                std::unique_lock<std::mutex> lock(_mutex);
                {
                    if (_service.count(service->method()) == true)
                    {
                        ERROR_LOG("已经注册过该成员方法！");
                        return;
                    }
                    _service.insert({service->method(), service});
                }
            }
            bool select(const std::string &method, ServiceDiscribe::Ptr &server)
            {
                std::unique_lock<std::mutex> lock(_mutex);
                {
                    if (_service.count(method) == false)
                    {
                        ERROR_LOG("未找到该方法，服务发现失败！");
                        server = ServiceDiscribe::Ptr();
                        return false;
                    }
                    server = _service[method];
                    return true;
                }
            }
            void remove(const std::string &method)
            {
                std::unique_lock<std::mutex> lock(_mutex);
                {
                    if (_service.count(method))
                    {
                        _service.erase(method);
                        return;
                    }
                }
                ERROR_LOG("要删除的服务不存在！");
            }

        private:
            std::mutex _mutex;
            std::unordered_map<std::string, ServiceDiscribe::Ptr> _service;
        };

        class RpcRouter
        {
        public:
            using Ptr = std::shared_ptr<RpcRouter>;
            // 这是dispatcher模块中的回调函数。
            void onRpcRequest(const BaseConnection::Ptr &conn, RpcRequest::Ptr &request)
            {
                // 1、查询客服端请求方法
                ServiceDiscribe::Ptr server;
                bool selret = _service_manager.select(request->method(), server);
                if (selret == false)
                {
                    ERROR_LOG("未发现对应的注册方法！");
                    request = RpcRequest::Ptr();
                    return response(conn, request, Json::Value(), RPC::RCode::RCODE_NOT_FOUND_RPC);
                }
                // 2、进行参数校验
                bool ckret = server->paramCheck(request->Param());
                if (ckret == false)
                {
                    ERROR_LOG("请求参数校验失败!");
                    return response(conn, request, Json::Value(), RPC::RCode::RCODE_INVALID_PARA_RPC);
                }
                // 3、调用业务回调接口，业务处理
                Json::Value res;
                bool svcret = server->call(request->Param(), res);
                if (svcret == false)
                {
                    ERROR_LOG("内部错误！");
                    return response(conn, request, Json::Value(), RPC::RCode::RCODE_INTERNAL_RPC);
                }
                // 4、处理完成得到结果，组织响应，向服务端发送。
                return response(conn, request, res, RPC::RCode::RCODE_OK);
            }

            void registerRequest(const ServiceDiscribe::Ptr &service)
            {
                _service_manager.create(service);
            }

        private:
            void response(const BaseConnection::Ptr &conn, const RpcRequest::Ptr &request,
                          const Json::Value &ret,
                          const RCode &code)
            {
                auto base_msg = MessageFactory::create<RpcResponse>();
                base_msg->setId(request->id());
                base_msg->setType(RPC::MType::RES_RPC);
                base_msg->setRCode(code);
                base_msg->setResult(ret);
                conn->send(base_msg);
            }
            

        private:
            ServiceManager _service_manager;
        };

        // class RouterFactory
        // {
        // public:
        //     template<typename ...Args>
        //     static RpcRouter::Ptr create(Args ...args)
        //     {
        //         return std::shared_ptr<RpcRouter>(args...);
        //     }
        // };
        class RouterFactory
        {
        public:
            template <typename... Args>
            static RpcRouter::Ptr create(Args... args)
            {
                // ❌ 不要这样：return std::make_shared<RpcRouter>(args...);
                // ✅ 正确：用 new，避免 static 构造
                return RpcRouter::Ptr(new RpcRouter(args...));
            }
        };
    }
}